package com.demo.spring.autowird;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

public class Autowired底层演示4 {
	
	public static void main(String[] args) throws Throwable {
		// GenericApplicationContext是一个干净的容器
		GenericApplicationContext context = new GenericApplicationContext();
		context.registerBeanDefinition("bean2", new AnnotatedGenericBeanDefinition(Bean2.class));
		context.registerBeanDefinition("bean3", new AnnotatedGenericBeanDefinition(Bean3.class));
		
		// 用于解析String等类型的属性
		context.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
		// 内嵌值解析器，用于解析${}
		context.getDefaultListableBeanFactory().addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);
		// 查找哪些属性、方法加了@Autowired，这称之为InjectionMetadata
		AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
		processor.setBeanFactory(context.getDefaultListableBeanFactory());
		
		// 手动创建bean1，此时肯定没有依赖注入
		Bean1 bean1 = new Bean1();
		System.out.println(bean1);
		
		// 演示的是Autowired底层演示3中inject方法执行的具体内容，就是找到每一个要注入的对象，进行注入
		// 获取bean1里的bean3属性
		Field bean3 = Bean1.class.getDeclaredField("bean3");
		// 把bean3属性封装为DependencyDescriptor
		DependencyDescriptor dd1 = new DependencyDescriptor(bean3, false);
		// 从容器得到bean3，后续就可以注入bean1
		Object o = context.getDefaultListableBeanFactory().doResolveDependency(dd1, "bean1", null, null);
		System.out.println(o);
		
		Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
		DependencyDescriptor dd2 = new DependencyDescriptor(new MethodParameter(setBean2, 0), false);
		Object o2 = context.getDefaultListableBeanFactory().doResolveDependency(dd2, "bean1", null, null);
		// 返回setBean2方法的入参bean2
		System.out.println(o2);
		
		Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
		DependencyDescriptor dd3 = new DependencyDescriptor(new MethodParameter(setHome, 0), false);
		Object o3 = context.getDefaultListableBeanFactory().doResolveDependency(dd3, "bean1", null, null);
		// 找到setHome方法的入参字符串
		System.out.println(o3);
	}

}
